﻿/*
 *      	基于MSP430FE425平台的Nokia 6100/3100 Lcd类的具体实现,该类实现并提供了
 *              嵌入式系统中显示的基本支持,对于字符的显示支持完全与标准C/C++相兼容,而
 *              作图函数由于本人能力有限所以看起来就相对比较简陋了,它只提供了对直线,圆
 *              和矩形函数的支持,如果你还需要更加强大的绘图函数,该类提供了一个万能函数
 *              接口cout<<Point(unsigned int x,unsigned int y)与cout<<set(ForGColor,unsigned int)
 *              相互配合使用,对点进行操作便函可你想获得的任何效果.
 *
 * 		作者：匿名
 *
 *		本软件为自由软件，你可以自由修改和发布.期望它能对你有所益处.
 *               
 *		最后修正时间：2008/10/5
 *		
 *		版权所有：中文中国
 */
#include "io.h"
#include "time.h"
#include "ctype.h"
#include "font.h"
#include "N6100.h"
#include "covert.h"
#include "string.h"
#include "math.h"
/*系统当前仅支持八位RGB色彩模式,所以将高八位与低八位取同一值
如果你想支持16位色彩你只需将"LowByte(value)//"注释掉即可
*/
#define  HighByte(value) LowByte(value)//(value>>8)
#define  LowByte(value) (value&0x00ff)

/*该函数是模拟I/0口的直接实现,如果用串口实现的话速度可能会更快,
但我没有试过,或许外接晶振提高cpu时钟也是一个不错的选择,如果你这
样做了,你将会发现这个函数工作得很好,但是如果你cpu时钟很低而且又
想获得出更好的工作效率的话,我建议你且串口实现.当然那样的话你可能
就要花上一些时间了.我就不陪你玩了.
*/
void _N6100::write(unsigned char datatemp,unsigned char mod)
{ 
      char i=9;
      out(N6100,SCE,0); 
      if(mod)
	      out(N6100,SDIN,1);
      else
              out(N6100,SDIN,0);
      out(N6100,SCLK,0); 
      out(N6100,SCLK,1); 
      while(i--){ 
              if(datatemp&0x80){
                      out(N6100,SDIN,1);
              } 
              else{
                      out(N6100,SDIN,0);
              } 
              out(N6100,SCLK,0); 
              out(N6100,SCLK,1); 
              datatemp<<=1; 
      } 
      out(N6100,SCE,1); 
      /*些句好像无实在的意义,你加上也是可以的它并不影响系统的工作,
      但是如果你想获得更好的速度的话或许看见它出现在这里你就不会那
      么高兴了,些你只要把干掉即可 
      */
      out(N6100,SDIN,1);
}
void _N6100::init(){
      open_io(N6100,RES,w);
      open_io(N6100,SCE,w);
      out(N6100,SCE,0);
      open_io(N6100,SDIN,w);
      open_io(N6100,SCLK,w);
      
      out(N6100,RES,0);
      delay(20); 
      out(N6100,RES,1);
      delay(20); 
      write(SLEEPOUT,COMMAND); // Sleep out  (command 0x11) 
      write(INVON,COMMAND);    // Inversion on  (command 0x20) , seems to be required for this controller 
     
      write(COLORMOD,COMMAND);  // Color Interface Pixel Format  (command 0x3A) 
      write(COLOR12,DATA);      // 0x03 = 12 bits-per-pixel 
      
      write(MOMACCTL,COMMAND);   // Memory access controller  (command 0x36).  
      write(0xC8,DATA);      // 0xC0 = mirror x and y, reverse rgb 
      
      write(SETCON,COMMAND);  // Write contrast  (command 0x25) 
      write(CONTRAST,DATA);      // contrast 0x30  
      delay(20); 
      
      write(DISPLAYON,COMMAND); // Display On  (command 0x29) 
}
 
//本函数为绘图函数,能绘制包括图形,图像,汉字能及英文在内的所有常驻用条符号,在本函数中我将所在的一
//切可显示的东西都抽像成图开,它们都有是矩形形状的,这们就将一切东西变的相当的简单了.
void _N6100::drawimage( const char* image,Rectangle rec){
        int i;
        char tempchar;
        int FONTSIZE=rec.width*rec.height/8;
        setBox(rec.xstart,rec.xstart+rec.width-1,rec.ystart,rec.ystart+rec.height-1);
        for(i=0;i<FONTSIZE;i++){
          tempchar=image[i];
          for(int n=8;n>0;n--){
                   if(tempchar&0x80){                                          
                      write(HighByte(ForGroundColor),DATA);
                      write(LowByte(ForGroundColor),DATA);
                    } 
                    else{                                        
                      write(HighByte(BackGroundColor),DATA);  
                      write(LowByte(BackGroundColor),DATA);
                    } 
                    tempchar<<=1;
          } 
        }
}
/*该函数为绘图函数,与失量图形不同,它仅用于位图的显示输出,但由于色彩的原因,
  其输出显示效果相当差,或许你显示的是一条猪,但你看见的可能像狗或者其它的,
  所以系统暂不支持位图的显示
*/
/*void _N6100::drawimage( const char* image,int xstart,int ystart,int width,int height){
        int len=0;
        for(int i=0;i<height;i++)
        for(int n=0;n<width;n++){
             write(ROWSET,COMMAND);     
              write(i,DATA);    
              write(i,DATA);     
              
              write(CLUSET,COMMAND);     
              write(n,DATA);     
              write(n,DATA);  
              write(RAMWRITE,COMMAND); 
              write(imag[len],DATA);
              write(0,DATA);
              len++;
        }
}*/
/*该函数只是对drawimage( const char* image,Rectangle rec)的简单调用,它
  的唯一好处就是省去了构造Rectangle对象的麻烦.
*/
void _N6100::drawimage( const char* image,int xstart,int ystart, int width, int height){
        Rectangle rec(xstart,ystart,width,height);
        drawimage(image,rec);
  
}


void _N6100::printf(char *str,int xstart,int ystart){    
      xcurrent=xstart;
      ycurrent=ystart;
      int length=0;
      char *tempstr=str;
      while(*tempstr++)length++;
      if(alignment==center&&length<=16)
          xcurrent=(132-length*8)/2;
      else if(alignment==right&&length<=16)
          xcurrent=(132-length*8);
      else
          xcurrent=0;
      while(*str){
        if(*str=='\n'){
              str++;
              ycurrent+=16;
              xcurrent=2;
              continue;
        }
         else if(*str=='\t'){
              str++;
              printf("    ",xcurrent,ycurrent);
        }
        else if(*str=='\a'){
              str++;
              printf("    ",xcurrent,ycurrent);
        }
        else if(*str=='\f'){
              str++;
              ycurrent+=16;
              
        }
        else if(*str=='\r'){
              str++;
              xcurrent=2;
              
        }
        else if(*str=='\b'){
              str++;
              xcurrent-=8;      
        }
        else if(*str<128){                    
              if((131-xcurrent)<7){
                    ycurrent+=16;
                    xcurrent=2;
              } 
              drawimage(ASCII+(*str-0x20)*16,xcurrent,ycurrent,8,16);  
              str++;
              xcurrent+=8;
              continue;
        }
        else{
              if((131-xcurrent)<15){
                    ycurrent+=16;
                    xcurrent=2;
              } 
              for(int n=0;n<50;n++){
                    if(*str==haizi[n].name[0]&&*(str+1)==haizi[n].name[1]){
                          drawimage(haizi[n].fontmod,xcurrent,ycurrent,16,16);
                          xcurrent+=16;
                          break;
                    }                    
              }
              str+=2;
              continue;
        }
      }

}

void _N6100::printf(float mod,char *str){
      printf(str,xcurrent,ycurrent);
}
/*void _N6100::setForGroundColor(unsigned char FGC){
      ForGroundColor=FGC;    
}

void setBackGroundColor(unsigned char BGC){
      BackGroundColor=BGC;    
}*/

void _N6100::line(int xstart,int ystart,int xstop,int ystop){
      int num;
      float ilong;
      float deline=(float)(ystop-ystart)/(float)(xstop-xstart);
      float xdeline=(float)(xstop-xstart)/(float)(ystop-ystart);
      if(deline>=1||deline<=-1){
           for(num=ystart;;){
                ilong=xstart+((num-ystart)*xdeline);
                setBox(ilong,ilong,num,num);
                write(HighByte(ForGroundColor),DATA);
                write(LowByte(ForGroundColor),DATA);
                if(ystart>ystop){
                  if(num>ystop){
                      num--;
                      continue; 
                  }
                  else return;
                } 
                else if(ystart<ystop){
                   if(num<ystop){
                      num++;
                      continue; 
                  }
                  else return;
                }

           }
      }    
      for(num=xstart;;){        
            ilong=ystart+((num-xstart)*deline);
            setBox(num,num,ilong,ilong);
            //write(ForGroundColor,DATA);
            //write(ForGroundColor,DATA);
            write(HighByte(ForGroundColor),DATA);
            write(LowByte(ForGroundColor),DATA);
            if(xstart>xstop){
                  if(num>xstop){
                      num--;
                      continue; 
                  }
                  else return;
                } 
                else if(xstart<xstop){
                   if(num<xstop){
                      num++;
                      continue; 
                  }
                  else return;
                }
      }
}

void _N6100::circle(int xstart,int ystart,int radius,float linewidth){
      int x,y,xx,yy,rr1,rr2;
      float result;
      for(x=xstart-radius;x<=xstart+radius;x++)
        for(y=ystart-radius;y<=ystart+radius;y++){
          xx=(x-xstart);
          yy=(y-ystart);
          result=xx*xx+yy*yy;
          xx=(radius-linewidth);
          yy=(radius+0.5);
          rr1=xx*xx;
          rr2=yy*yy;
          if(result>=rr1&&result<=rr2){
                setBox(x,x,y,y);
                //write(ForGroundColor,DATA);
                //write(ForGroundColor,DATA);  
                write(HighByte(ForGroundColor),DATA);
                write(LowByte(ForGroundColor),DATA);
          }
        }    
  
}

void _N6100::rectangle(int xstart,int ystart,int width,int height,unsigned char fill){
                int i=width*height;
                setBox(xstart,xstart+width-1,ystart,ystart+height-1);
                while(i--){
                write(fill,DATA);
                write(fill,DATA);   
                }
                
}

void _N6100::setBox(int xstart,int xstop,int ystart,int ystop){
        write(ROWSET,COMMAND);     
        write(ystart,DATA);    
        write(ystop,DATA);     
        
        write(CLUSET,COMMAND);     
        write(xstart,DATA);     
        write(xstop,DATA);  
        write(RAMWRITE,COMMAND);  
}

void _N6100::clear(){
        int size=17150;
        write(ROWSET,COMMAND);      
        write(0,DATA);     
        write(131,DATA);          
        write(CLUSET,COMMAND);   
        write(0,DATA);    
        write(131,DATA);  
        write(RAMWRITE,COMMAND);
        //setBox(0,0,131,131);
        while(size--){
             //write(ScrGroundColor,DATA);
             //write(ScrGroundColor,DATA);
             write(HighByte(ScrGroundColor),DATA);
             write(LowByte(ScrGroundColor),DATA);
        }
}

_N6100::_N6100(unsigned int BackGroundColor,unsigned int ForGroundColor,unsigned int ScrGroundColor){
        xcurrent=2;
        ycurrent=2;
        this->BackGroundColor=BackGroundColor;
        this->ForGroundColor=ForGroundColor;
        this->ScrGroundColor=ScrGroundColor;
        alignment=left;
        precision=10000;
        init();
        //clear();
}

_N6100 & _N6100::operator <<(char *str){
    printf(0.1,str);
    return *this;
}

_N6100 & _N6100::operator <<(int num){
    printf(0.1,itoa(num));
    return *this;
}

_N6100 & _N6100::operator <<(float num){
    char *str=new char[11];
    int i=(int)num;
    int n=(int)((num-i)*precision);
    strcpy(str,itoa(i));
    if(precision){
        strcat(str,".");
        strcat(str,itoa(n));
    }
    printf(0.1,str);
    delete str;
    return *this;
}


_N6100 & _N6100::operator <<(Point point){
      setBox(point.x,point.x,point.y,point.y);
      //write(ForGroundColor,DATA);
      //write(ForGroundColor,DATA);
      write(HighByte(ForGroundColor),DATA);
      write(LowByte(ForGroundColor),DATA);
      return *this;
}
_N6100 & _N6100::operator <<(Line lin){
      line(lin.xstart,lin.ystart,lin.xstop,lin.ystop);
      return *this;
}

_N6100 & _N6100::operator <<(WaveLine wavlin){
      int height=0;
      int i=0;
      bool add=false;   
      while(i<wavlin.length){
        if(!wavlin.vertical)
          *this<<Point(wavlin.xstart+height,wavlin.ystart+i);
        else
          *this<<Point(wavlin.xstart+i,wavlin.ystart+height);
          //*this<<Point(wavlin.xstart+i,wavlin.ystart);
          if(height==wavlin.height)
            add=false;
          else if(height==-wavlin.height)
            add=true;
          height+=add?1:-1;
          i+=1;
      }             
      return *this;
}
_N6100 & _N6100::operator <<(Rectangle rec){
        if(!rec.fillcolor)
            rectangle(rec.xstart,rec.ystart,rec.width,rec.height,ForGroundColor);
        else
            rectangle(rec.xstart,rec.ystart,rec.width,rec.height,rec.fillcolor);
        if(rec.linewidth)
            rectangle(rec.xstart+rec.linewidth,rec.ystart+rec.linewidth,rec.width-rec.linewidth-rec.linewidth,rec.height-rec.linewidth-rec.linewidth,ScrGroundColor);
        return *this;
}

_N6100 & _N6100::operator <<(Circle cir){
        circle(cir.xstart,cir.ystart,cir.radius,cir.linewidth);
        return *this;
} 

_N6100 & _N6100::operator <<(set setp){
        switch(setp.name){
              case ForGColor:this->ForGroundColor=setp.color;break;
              case BackGColor:this->BackGroundColor=setp.color;break;  
              case XCurrent:this->xcurrent=setp.position;break;
              case YCurrent:this->ycurrent=setp.position;break;
              case ScrGColor:this->ScrGroundColor=setp.color;break;
              case Left:this->alignment=left;break;
              case Right:this->alignment=right;break;
              case Center:this->alignment=center;break;
              case Precision:this->precision=setp.color;
        }           
        return *this;           
}

_N6100 & _N6100::operator <<(invalidate inv){
        rectangle(inv.xstart,inv.ystart,inv.width,inv.height,this->ScrGroundColor);
        return *this;
}
_N6100 & _N6100::operator <<(char ch){
        char str[]={ch,0};
        printf(0.1,str);
        return *this;
} 

_N6100 & _N6100::operator >>(char *str){
        strcpy(buffer.buffer,str);
        return *this;
}

_N6100 & _N6100::operator <<(_N6100 *str){
        printf(0.1,buffer.buffer);
        return *this;
}
void _N6100::waveLine(){
        int x;
        int y;
        *this<<Point(10,10);
        for(x=0;x<100;x++){
            y=pow(x,2)/100;
            setBox(x,x,y,y);
             //write(ForGroundColor,DATA);
             //write(ForGroundColor,DATA);
            write(HighByte(ForGroundColor),DATA);
            write(LowByte(ForGroundColor),DATA);
        }
}
_N6100 cout(Color::White,Color::Black,Color::White);

